/*
 * Material.h
 *
 *  Created on: Feb 15, 2011
 *      Author: alki
 */

#ifndef MATERIAL_H_
#define MATERIAL_H_

class FARBE;
class Material;

#include "Textur.h"

/**
 * Klasse Farbe: RGB-Werte und deren Berechnungen
 */
class FARBE {
public:
	FARBE() {r=0;g=0;b=0;}
	FARBE(float rn,float gn,float bn) {r=rn;g=gn;b=bn;}

	FARBE operator+(FARBE add) const { return FARBE(this->r+add.r,this->g+add.g,this->b+add.b); }
	void operator+=(FARBE add) { FARBE(this->r+=add.r,this->g+=add.g,this->b+=add.b); }
	FARBE operator*(FARBE mul) const { return FARBE(this->r*mul.r,this->g*mul.g,this->b*mul.b); }
	FARBE operator*(float mul) const { return FARBE(this->r*mul,this->g*mul,this->b*mul); }
	FARBE operator/(float div) const { return FARBE(this->r/div,this->g/div,this->b/div); }

	bool operator==(FARBE vergleich) const;
	bool operator!=(FARBE vergleich) const { return !((*this)==vergleich); }

	void MAX() { r=(r>1)?1:r; g=(g>1)?1:g; b=(b>1)?1:b; }
	bool FULL() { return (r==1)&&(g==1)&&(b==1); }
	bool DARK() { return (r==0)&&(g==0)&&(b==0); }

	float r;
	float g;
	float b;
};

/**
 * Klasse Material: Managed die Materialien mit den verschiedenen Farb-Anteilen und Texturen
 */
class Material {
public:
	Material();
	virtual ~Material();

	void setTextur(Textur *t) { this->m_textur = t; }
	void setTexCoords(float u,float v) { this->m_u = u; this->m_v = v; }
	void setLightAmbient(FARBE a) { this->m_ambient = a; }
	void setLightDiffus(FARBE d) { this->m_diffus = d; }
	void setLightSpecular(FARBE s) { this->m_specular = s; }
	void setLightEmissive(FARBE e) { this->m_emissive = e; }

	Textur *getTextur() const { return this->m_textur; }
	void getTexCoords(float *u,float *v) const { if(!u||!v)return; *u=this->m_u;*v=this->m_v; }
	FARBE getTexColor() const;
	FARBE getLightAmbient() const { return this->m_ambient; }
	FARBE getLightDiffus() const { return this->m_diffus; }
	FARBE getLightSpecular() const { return this->m_specular; }
	FARBE getLightEmissive() const { return this->m_emissive; }

	void setTransmission(float t) { this->m_transmission = (t>1)?1:((t<0)?0:t); }
	void setReflexion(float r) { this->m_reflexion = (r>1)?1:((r<0)?0:r); }
	void setBrechung(float n) { this->m_brechung = (n<1)?1:n; }
	void setSpecularExponent(unsigned int e) { this->m_specexp = e; }
	void setDiffusFaktor(float d) { this->m_diffusfaktor = (d>1)?1:((d<0)?0:d); }
	void setSpecularFaktor(float s) { this->m_specularfaktor = (s>1)?1:((s<0)?0:s); }

	float getReflexion() const { return this->m_reflexion; }
	unsigned int getSpecularExponent() const { return this->m_specexp; }
	float getDiffusFaktor() const { return this->m_diffusfaktor; }
	float getSpecularFaktor() const { return this->m_specularfaktor; }

	bool operator==(Material vergleich) const;
	bool operator!=(Material vergleich) const { return !(*this==vergleich); }

private:
	/**
	 * die verschiedenen Farbanteile
	 */
	FARBE m_ambient;
	FARBE m_diffus;
	FARBE m_specular;
	FARBE m_emissive;

	/**
	 * - Anteil der Transmission
	 * - Anteil der Reflexion
	 * - Brechungsindex
	 * - Exponent des Spekulären Anteils (je höher, desto reflexiver)
	 * - Anteil des diffusen Lichts
	 * - Anteil des Speculären Lichts
	 */
	float m_transmission;
	float m_reflexion;
	float m_brechung;
	unsigned int m_specexp;
	float m_diffusfaktor;
	float m_specularfaktor;

	/**
	 * Textur mit baryzentrischen Koordinaten (diese werden nur für die Berechnung benötigt!)
	 */
	Textur *m_textur;
	float m_u;
	float m_v;
};

#endif /* MATERIAL_H_ */
